package com.authine.cloudpivot.ext.controller;

import cn.hutool.core.text.StrFormatter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.engine.api.model.organization.DepartmentModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectCreatedModel;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author hxd
 * @Date 2021/11/2 15:30
 * @Description 客户自定义二开接口
 **/

@RestController
@RequestMapping("/customer/opt")
@Slf4j
public class CustController extends BaseController {


    @GetMapping("getDeptByIdAndLeave")
    public ResponseResult<DepartmentModel> getDeptByIdAndLeave(@RequestParam String deptId,@RequestParam(required = false,defaultValue = "1") Integer leave)  {

        List<DepartmentModel> list = getOrganizationFacade().getParentDepartments(deptId);

        if(list.size() <= leave ){
            return getErrResponseResult(null,-1l,"未获取到组织");
        }

        if (list.isEmpty()) {
            return getErrResponseResult(null,-1l,"未获取到上级组织");
        }if(list.size()==1){
            return getOkResponseResult(list.get(0),"");
        }


        return getOkResponseResult(list.get(list.size()-leave-1),"");
    }

    @GetMapping("getDeptListByIdAndLeave")
    public ResponseResult getDeptListByIdAndLeave(@RequestParam List<String> deptIds,@RequestParam(required = false,defaultValue = "1") Integer leave){


        if(deptIds == null || deptIds.isEmpty()){
            return getErrResponseResult(-1l,"参数不能为空");
        }
        List<DepartmentModel> collect = deptIds.stream().distinct().map(a -> {
            ResponseResult<DepartmentModel> rst = getDeptByIdAndLeave(a, leave);

            if (rst.getErrcode() == 0l) {
                return rst.getData();
            }
            return null;
        }).filter(Objects::nonNull)
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new ConcurrentSkipListSet<>(Comparator.comparing(DepartmentModel::getId))), ArrayList::new));

        return getOkResponseResult(collect,"");
    }

    @GetMapping("getBizObject")
    public ResponseResult getBizObject(String schemaCode,String id){
        BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(schemaCode, id);

        return getOkResponseResult(bizObject,"成功");
    }


    @PersistenceContext
    EntityManager entityManager;


    static boolean flag = false;
    @GetMapping("test")
    public void test(){

        if (flag){
            log.info("\n========已执行过");
            return;
        }


        String  sql = "SELECT biz.id, pack.name appName, func.name modelName,pack.appNameSpace , concat(\"i\", pack.appNameSpace, \"_\", func.code) as tbName FROM h_biz_sheet biz INNER JOIN h_app_function func ON func.code = biz.schemaCode INNER JOIN h_app_package pack ON \n" +
                "pack.code = func.appCode WHERE TRIM(publishedAttributesJson) LIKE '%format%\":\"ratio%'  ;";


        List<Map<String,String>> resultList = entityManager.createNativeQuery(sql)
                .unwrap(NativeQueryImpl.class)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).getResultList();


        log.info("\n===================resultList:{}\n", JSON.toJSONString(resultList));

        String sheetIdList = resultList.stream().map(m -> m.get("id")).collect(Collectors.joining("','"));

        log.info("\n===================sheetIdList:{}\n", sheetIdList);

        Map<String, Map<String, String>> IdMap = resultList.stream().collect(Collectors.toMap(m -> m.get("id"), Function.identity(), (k1, k2) -> k1));

        sql = new StringBuilder("SELECT id, publishedAttributesJson from h_biz_sheet where id in ('").append(sheetIdList).append("')").toString();

        List<Map<String,String>> attrs = entityManager.createNativeQuery(sql)
                .unwrap(NativeQueryImpl.class)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).getResultList();

        List<String> tbList = new ArrayList<>();
        List<String> updateSqlList = new ArrayList<>();


        attrs.stream().forEach(m->{

            String id = m.get("id");
            String str = m.get("publishedAttributesJson");
            Map<String, String> appMap = IdMap.get(id);
            String appName = appMap.get("appName");
            String modelName = appMap.get("modelName");
            String appNameSpace = appMap.get("appNameSpace");
            String tbName = appMap.get("tbName");

            List<Map<String, String>> masterPropertyList = new ArrayList<>();
            List<Map<String, Object>> subList = new ArrayList<>();

            JSONObject j1 = (JSONObject) JSON.parse(str);

            Set<String> sets = j1.keySet();


            sets.stream().forEach(k1 ->{
                JSONObject j2 = j1.getJSONObject(k1);
                //解析json
                processingJson(masterPropertyList, subList, j2);
            });

            //处理及拼接sql
            StringBuilder sbr = new StringBuilder(StrFormatter.format("\n===========应用:{},模型:{} ===================\n",appName,modelName));
            StringBuilder sqlJoin = new StringBuilder();
            if (!masterPropertyList.isEmpty()){
                //主表属性字段
                List<String> mstList = masterPropertyList.stream().map(m1 ->m1.get("name").concat(":").concat(m1.get("key")) ).collect(Collectors.toList());
                sbr.append("主表:").append(tbName).append(";属性:[").append(StringUtils.join(mstList,",")).append("]\n");

                mstList = masterPropertyList.stream().map(m1 -> m1.get("key")).collect(Collectors.toList());
                sqlJoin.append("\n-- 更新表: ").append(tbName).append("\n update ").append(tbName).append(" set ")
                    .append(mstList.stream().map(key->key.concat(" = ").concat(key).concat("/100 ")).collect(Collectors.joining(",")))
                    .append(";\n");
            }

            if (!subList.isEmpty()){
                //包含子表code


                subList.stream().forEach(m2->{

                    String subTbName = "i".concat(appNameSpace).concat("_").concat(m2.get("key").toString());
                    List<Map<String, String>> columns = (List<Map<String, String>>) m2.get("columns");
                    List<String> subPropertyList = columns.stream().map(m3 -> m3.get("name").concat(":").concat( m3.get("key"))).collect(Collectors.toList());

                    sbr.append("子表:").append(subTbName).append(";子表属性:[").append(StringUtils.join(subPropertyList,",")).append("]\n");

                    subPropertyList = columns.stream().map(m3 -> m3.get("key")).collect(Collectors.toList());
                    sqlJoin.append("\n-- 更新表: ").append(subTbName).append("\n update ").append(subTbName).append(" set ")
                            .append(subPropertyList.stream().map(key->key.concat(" = ").concat(key).concat("/100 ")).collect(Collectors.joining(",")))
                            .append(";\n");
                });


            }

            tbList.add(sbr.toString());
            updateSqlList.add(sqlJoin.toString());

        });



        log.info("\n==============需要更新的表信息:{}\n==============需要执行的sql:{}",StringUtils.join(tbList,""),StringUtils.join(updateSqlList,""));

        tbList.clear();
        updateSqlList.clear();

        flag = true;
    }

    private void processingJson(final List<Map<String, String>> masterPropertyList, final List<Map<String, Object>> subList,   final JSONObject j2) {
        int type = j2.getInteger("type").intValue();

        if (type == 4 ){
            //获取字段
            extracted1(masterPropertyList, j2);
        }else if(type == 201){
            //获取子表
            JSONArray columns = j2.getJSONArray("columns");

            if (columns != null  ) {

                List<Map<String, String>> subPropertyList = new ArrayList<>();

                columns.stream().forEach(s->{
                    JSONObject s1 = (JSONObject) s;

                    if ( s1.getInteger("type").intValue() ==4){
                        //获取子表字段
                        extracted1(subPropertyList, s1);
                    }

                });
                if (!subPropertyList.isEmpty()){
                    Map<String, Object> subMap = new HashMap<>();
                    subMap.put("key", j2.getString("key"));
                    subMap.put("columns",subPropertyList);
                    subList.add(subMap);
                }

            }

        }else if(type ==500){
            //标签页处理
            JSONArray panels = j2.getJSONArray("panels");

            if (panels != null && panels.size()>0) {
                panels.stream().forEach(p->{
                    JSONObject ctls1 = (JSONObject) p;
                    JSONObject ctls2 = ctls1.getJSONObject("controls");
                    ctls2.keySet().stream().forEach(ckey->{
                        JSONObject ctls3 = ctls2.getJSONObject(ckey);
                        //递归解析标签页面里的json
                        processingJson(masterPropertyList, subList, ctls3);
                    });

                });
            }

        }
    }

    private void extracted1(final List<Map<String, String>> zpList, final JSONObject s1) {
        JSONObject options = s1.getJSONObject("options");

        String format1 = options.getString("format");

        if (format1 != null && format1.startsWith("ratio")) {
            Map<String, String> property = new HashMap<>();
            property.put("key", s1.getString("key"));
            property.put("name", options.getString("name"));
            zpList.add(property);

        }
    }

}
